package tr.richfacesext.components.imgviewer;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.Set;

import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 * @author mert
 *
 */
public class ImgViewerPhaseListener implements PhaseListener {

	public void beforePhase(PhaseEvent event) {
		//No-op
	}

	public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}

	@SuppressWarnings("unchecked")
	public void afterPhase(PhaseEvent event) {
		FacesContext context = event.getFacesContext();
		String viewRootId = context.getViewRoot().getViewId();
		Map requestParamMap = getExternalContext(context).getRequestParameterMap();
		
		if (viewRootContainsPLKey(viewRootId) && requestParamMap.containsKey(ImgViewerConstants.KEYVAL_IMAGEID)) {
			serveImage(context, (String) requestParamMap.get(ImgViewerConstants.KEYVAL_IMAGEID));
		}
	}

	@SuppressWarnings("unchecked")
	private void serveImage(FacesContext context, String id) {
		HttpServletResponse response = (HttpServletResponse) getExternalContext(context).getResponse();
		Map sessionMap = getExternalContext(context).getSessionMap();
		 Set<String> keys=sessionMap.keySet();
		 String keyMatched=null;
		 for (String key : keys) {
			if(key.endsWith(id))
				keyMatched=key;
			
		}
		 
		if(keyMatched==null)
			keyMatched=id;
		BufferedImage bufferedImg = (BufferedImage) sessionMap.get(keyMatched);
		if(bufferedImg == null){
			//log.warn("Null BufferedImage in Session for id: " + id);
			return;
		}
		try {
			writeImageWithServletResponse(response, bufferedImg);
		} 
		catch (Exception e) {
			throw new FacesException("Error occurred while serving image", e);
		} 
		finally {
			emptySession(sessionMap, id);
			context.responseComplete();
		}
	}

	private void writeImageWithServletResponse(HttpServletResponse response, BufferedImage bufferedImage) {
		try {
			OutputStream outputStream = response.getOutputStream();
			
			// Write-out the buffered img as jpg type
			// Doesn't matter if you have the png, bmp or gif
			ImageIO.write(bufferedImage, "jpg", outputStream);
			outputStream.close();
			outputStream.flush();
		} 
		catch (IOException e) {
			throw new FacesException("Error while outputting image", e);
		}
	}
	
	private ExternalContext getExternalContext(FacesContext context) {
		return context.getExternalContext();
	}

	private boolean viewRootContainsPLKey(String viewRootId) {
		return viewRootId.contains(ImgViewerConstants.IMAGEVIEWER_VIEW_ID.substring(0, ImgViewerConstants.IMAGEVIEWER_VIEW_ID.lastIndexOf(".")));
	}
	
	@SuppressWarnings("unchecked")
	private void emptySession(Map sessionMap, String imageId) {
		sessionMap.remove(imageId);
	}

}
